;
; Copyright (c) Microsoft Corporation.  All rights reserved.
;
;
; Use of this sample source code is subject to the terms of the Microsoft
; license agreement under which you licensed this sample source code. If
; you did not accept the terms of the license agreement, you are not
; authorized to use this sample source code. For the terms of the license,
; please see the license agreement between you and Microsoft or, if applicable,
; see the LICENSE.RTF on your install media or the root of your tools installation.
; THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
;
;
; (C) Copyright 2006 Marvell International Ltd.
; All Rights Reserved
;
; Copyright (c) 1998, 1999 ARM Limited
; All Rights Reserved
;

    OPT     2       ; disable listing
    INCLUDE kxarm.h
    OPT     1       ; reenable listing
    OPT     128     ; disable listing of macro expansions
    INCLUDE armmacros.s

    TEXTAREA

;++
; Routine Description:
;    Invalidate a range of L2 cache lines, based on translated MVA.
;
; Syntax:
;	void XScaleFlushL2LinesMVA(PVOID pAddr, DWORD dwLength, DWORD dwLineLength);
;
; Arguments:
;	r0: pAddr -- virtual address at which to start cleaning, on dwLineLength-byte 
;            alignment
;	r1: dwLength -- number of bytes to cleaning, must be > zero
;        r2: dwLineLength -- number of bytes in a cache line
;
; Return Value:
;	-- none --
; r0..r2 junk
; CC flags junk	
;--
    LEAF_ENTRY	XScaleFlushL2LinesMVA

    ; clean the range of lines
10
    mcr 	p15, 1, r0, c7, c7, 1   ; clean each entry
    add  r0, r0, r2              ; on to the next line
    subs	r1, r1, r2              ; reduce the number of bytes left
    bgt  %b10                    ; loop while > 0 bytes left

    mcr     p15, 0, r2, c7, c10, 4      ; data write barrier
    
    RETURN


;++
; Routine Description:
;    Invalidate the entire L2 cache by set/way.  No write-backs.
;
; Syntax:
;	void XScaleGlobalInvalidateL2Cache(DWORD cachesize);
;
; Arguments:
;	r0: cachesize -- the size of the L2 cache.  Used to determine correct algorithm.
;            
; Expected use scenarios:  any time you need to flush to RAM.  Low power mode entry, for example, where the L2 is lost.
; Return Value:
;	-- none --
; r0-r4 junk
; CC flags junk	
;--
    LEAF_ENTRY	XScaleGlobalInvalidateL2Cache

    ; clean the range of lines by set/way.
    stmdb   sp!, {r0-r7}    
    
    ; 512 KB case
;    mov r0, #0xFF00

    ;256k cache
    mov r0, #0x7F00
    
    orr r0, r0, #0x00E0        ; put NSets (2048)-1 into bits 15:5, way 0
    add r1, r0, #0x20000000    ; index for way 1
    add r2, r1, #0x20000000    ; index for way 2
    add r3, r2, #0x20000000    ; index for way 3
    add r4, r3, #0x20000000    ; index for way 4
    add r5, r4, #0x20000000    ; index for way 5
    add r6, r5, #0x20000000    ; index for way 6
    add r7, r6, #0x20000000    ; index for way 7
    
1
    mcr p15, 1, r0, c7, c7, 1  ; inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r1, c7, c7, 1  ; inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r2, c7, c7, 1  ; inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r3, c7, c7, 1  ; inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r4, c7, c7, 1  ; inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r5, c7, c7, 1  ; inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r6, c7, c7, 1  ; inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r7, c7, c7, 1  ; inv set/way0 of L1 dcache specified in r0

 
    subs r0, r0, #0x00000020   ; decrement the shifted set index (way0)
    sub  r1, r1, #0x00000020   ; decrement the shifted set index (way1)
    sub  r2, r2, #0x00000020   ; decrement the shifted set index (way2)
    sub  r3, r3, #0x00000020   ; decrement the shifted set index (way3)
    sub  r4, r4, #0x00000020   ; decrement the shifted set index (way4)
    sub  r5, r5, #0x00000020   ; decrement the shifted set index (way5)
    sub  r6, r6, #0x00000020   ; decrement the shifted set index (way6)
    sub  r7, r7, #0x00000020   ; decrement the shifted set index (way7)
    
    bpl %BT1                   ; go to next set if not done with all sets

    ; set up a data write barrier
    mcr     p15, 0, r0, c7, c10, 4

    ldmia   sp!, {r0-r7}   
    
    RETURN
    


;++
; Routine Description:
;    Invalidate and clean the entire L2 cache by set/way.  Write-back dirtied lines.
;
; Syntax:
;	void XScaleGlobalFlushL2Cache(DWORD cachesize);
;
; Arguments:
;	r0: cachesize -- the size of the L2 cache.  Used to determine correct algorithm.
;            
; Expected use scenarios:  any time you need to flush to RAM.  Low power mode entry, for example, where the L2 is lost.
; Return Value:
;	-- none --
; r0-r4 junk
; CC flags junk	
;--
    LEAF_ENTRY	XScaleGlobalFlushL2Cache

    ; clean the range of lines by set/way.
    stmdb   sp!, {r0-r7}    
    
    ; 512 KB case
;    mov r0, #0xFF00

    ;256K cache
    mov r0, #0x7F00

    orr r0, r0, #0x00E0        ; put NSets (2048)-1 into bits 15:5, way 0
    add r1, r0, #0x20000000    ; index for way 1
    add r2, r1, #0x20000000    ; index for way 2
    add r3, r2, #0x20000000    ; index for way 3
    add r4, r3, #0x20000000    ; index for way 4
    add r5, r4, #0x20000000    ; index for way 5
    add r6, r5, #0x20000000    ; index for way 6
    add r7, r6, #0x20000000    ; index for way 7
    
1
    mcr p15, 1, r0, c7, c15, 2  ; clean&inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r1, c7, c15, 2  ; clean&inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r2, c7, c15, 2  ; clean&inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r3, c7, c15, 2  ; clean&inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r4, c7, c15, 2  ; clean&inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r5, c7, c15, 2  ; clean&inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r6, c7, c15, 2  ; clean&inv set/way0 of L1 dcache specified in r0
    mcr p15, 1, r7, c7, c15, 2  ; clean&inv set/way0 of L1 dcache specified in r0

 
    subs r0, r0, #0x00000020   ; decrement the shifted set index (way0)
    sub  r1, r1, #0x00000020   ; decrement the shifted set index (way1)
    sub  r2, r2, #0x00000020   ; decrement the shifted set index (way2)
    sub  r3, r3, #0x00000020   ; decrement the shifted set index (way3)
    sub  r4, r4, #0x00000020   ; decrement the shifted set index (way4)
    sub  r5, r5, #0x00000020   ; decrement the shifted set index (way5)
    sub  r6, r6, #0x00000020   ; decrement the shifted set index (way6)
    sub  r7, r7, #0x00000020   ; decrement the shifted set index (way7)
    
    bpl %BT1                   ; go to next set if not done with all sets

    ; set up a data write barrier
    mcr     p15, 0, r0, c7, c10, 4

    ldmia   sp!, {r0-r7}   
    
    RETURN
    
       
;++
; Routine Description:
;    Detect if L2 cache is present.
;
; Syntax:
;	BOOL XScaleIsL2CachePresent(void);
;
; Arguments:
;
; Return Value: '0' is no L2 cache is present, otherwise a '1'.
;	
;
; r0 junk
;--
    LEAF_ENTRY	XScaleIsL2CachePresent

    mrc  p15, 1, r0, c0, c0, 1
    mov  r0, r0 LSR #6
    
    RETURN


;++
; Routine Description:
;    Detect size of L2 cache.
;
; Syntax:
;	DWORD XScaleGetL2CacheSize(void);
;
; Arguments:
;
; Return Value: The size of the cache (in bytes) is returned in r0 (0x8_0000 | 0x4_0000)
;	
;
; r0..r2 junk
; CC flags junk	
;--
    LEAF_ENTRY XScaleGetL2CacheSize

    ; debug:  just return the L2 cache type register
    mrc  p15, 1, r0, c0, c0, 1 
    
    RETURN
       
;------------------------------------------------------------------------------       
    END
